package com.xbongbong.paas.service.impl;/*/*/

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.enums.ProcessSaasAppEnum;
import com.xbongbong.paas.enums.ProcessSaasFormEnum;
import com.xbongbong.paas.enums.ProcessSearchStatusAllEnum;
import com.xbongbong.paas.enums.ProcessSearchStatusCcEnum;
import com.xbongbong.paas.enums.ProcessSearchStatusCreateEnum;
import com.xbongbong.paas.enums.ProcessSearchStatusTodoEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.clazz.ProcessTypeClass;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.ProcessTypeListDTO;
import com.xbongbong.paas.pojo.vo.ProcessTypeListVO;
import com.xbongbong.paas.service.PaasProcessListSearchService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.pojo.AppPermissionPojo;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.process.pojo.ProcessAppFilterPojo;
import com.xbongbong.pro.process.pojo.ProcessFormFilterPojo;
import com.xbongbong.pro.process.pojo.dto.ProcessAppFilterDTO;
import com.xbongbong.pro.process.pojo.dto.ProcessFormFilterDTO;
import com.xbongbong.pro.process.pojo.vo.ProcessAppFilterVO;
import com.xbongbong.pro.process.pojo.vo.ProcessFormFilterVO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * Description: 流程列表筛选
 *
 * @author 李杰
 * @version v1.0
 * @date 2019/1/22 14:13
 * @since v1.0
 */
@Service("paasProcessListSearchService")
public class PaasProcessListSearchServiceImpl implements PaasProcessListSearchService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasProcessListSearchServiceImpl.class);

    @Resource
    private PaasAppModel appModel;
    @Resource
    private PaasMenuModel menuModel;

    @Override
    public ProcessAppFilterVO appFilter(ProcessAppFilterDTO processAppFilterDTO) throws XbbException {
        ProcessAppFilterVO processAppFilterVO = new ProcessAppFilterVO();
        try {
            UserVO userVO = processAppFilterDTO.getLoginUser();
            Set<String> saasPermissions = userVO.getPermSet();
            boolean isAdmin = userVO.isAdminOrBoss();
            String paasPermissions = userVO.getPaasPermissions();
            List<AppPermissionPojo> appPermissions = JSON.parseArray(paasPermissions, AppPermissionPojo.class);
            if (appPermissions == null) {
                appPermissions = new ArrayList<>();
            }
            Map<Long, AppPermissionPojo> permMap = new HashMap<>(appPermissions.size());
            for (AppPermissionPojo appPermission : appPermissions) {
                permMap.put(appPermission.getAppId(), appPermission);
            }
            Map<String, Object> param = BeanUtil.convertBean2Map(processAppFilterDTO, true);
            param.put("orderByStr", "sort");
            param.put("enable", 1);
            List<PaasAppEntity> appEntityList = appModel.list(param);
            if (appEntityList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }

            List<ProcessAppFilterPojo> appList = new ArrayList<>();
            // PaaS应用列表
            appEntityList.forEach((item) -> {
                if (Objects.equals(item.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                    for (ProcessSaasAppEnum appEnum : ProcessSaasAppEnum.values()) {
                        if ((Objects.equals(item.getAlias(), appEnum.getAlias()) && saasPermissions.contains(item.getAlias()))) {
                            ProcessAppFilterPojo processAppFilterPojo = new ProcessAppFilterPojo();
                            processAppFilterPojo.setId(item.getId());
                            processAppFilterPojo.setSaasAppType(appEnum.getType());
                            processAppFilterPojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
                            processAppFilterPojo.setName(item.getName());
                            appList.add(processAppFilterPojo);
                            break;
                        }
                    }
                } else {
                    if (isAdmin || permMap.containsKey(item.getId())) {
                        ProcessAppFilterPojo processAppFilterPojo = new ProcessAppFilterPojo();
                        BeanUtil.copyProperties(item, processAppFilterPojo);
                        appList.add(processAppFilterPojo);
                    }
                }
            });
            processAppFilterVO.setList(appList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasApp数据库查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processAppFilterVO;
    }

    @Override
    public ProcessFormFilterVO formFilter(ProcessFormFilterDTO processFormFilterDTO) throws XbbException {
        ProcessFormFilterVO processFormFilterVO = new ProcessFormFilterVO();
        List<ProcessFormFilterPojo> formFilterPojoList = new ArrayList<>();
        UserVO userVO = processFormFilterDTO.getLoginUser();
        Set<String> saasPermissions = userVO.getPermSet();
        boolean isAdmin = userVO.isAdminOrBoss();
        String paasPermissions = userVO.getPaasPermissions();
        List<AppPermissionPojo> appPermissions = JSON.parseArray(paasPermissions, AppPermissionPojo.class);
        if (appPermissions == null) {
            appPermissions = new ArrayList<>();
        }
        Set<Long> menuPermSet = new HashSet<>();
        for (AppPermissionPojo appPermission : appPermissions) {
            appPermission.getModules().forEach(item -> menuPermSet.add(item.getId()));
        }
        // 记录
        Map<String, String> saasMenuNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {
            if (Objects.equals(processFormFilterDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                Integer appType = processFormFilterDTO.getSaasAppType();
                if (appType == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                List<String> saasAlias = new ArrayList<>();
                Map<String, Long> saasMenuIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<ProcessSaasFormEnum> businessTypeList = ProcessSaasFormEnum.getFormEnumList(appType);
                for (ProcessSaasFormEnum formEnum : businessTypeList) {
                    if (saasPermissions.contains(formEnum.getAlias())) {
                        saasAlias.add(ProcessSaasFormEnum.transfer2Saas(formEnum).getAlias());
                    }
                }
                Map<String, Object> param = BeanUtil.convertBean2Map(processFormFilterDTO, true);
                param.put("saasMark", SaasMarkEnum.SAAS.getCode());
                param.put("aliasIn", saasAlias);
                List<PaasMenuEntity> saasMenuList = menuModel.list(param);
                saasMenuList.forEach((item) -> {
                    saasMenuIdMap.put(item.getAlias() + StringConstant.UNDER_LINE + item.getDistributorMark(), item.getId());
                    saasMenuNameMap.put(item.getAlias() + StringConstant.UNDER_LINE + item.getDistributorMark(), item.getName());
                });
                for (ProcessSaasFormEnum formEnum : businessTypeList) {
                    if (saasPermissions.contains(formEnum.getAlias())) {
                        ProcessFormFilterPojo processFormFilterPojo = new ProcessFormFilterPojo();
                        processFormFilterPojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        processFormFilterPojo.setBusinessType(XbbRefTypeEnum.transferBusinessType2Index(formEnum.getBusinessType()));
                        String key = ProcessSaasFormEnum.transfer2Saas(formEnum).getAlias() + StringConstant.UNDER_LINE + formEnum.getDistributorMark();
                        String name = saasMenuNameMap.get(key);
                        Long id = saasMenuIdMap.get(key);
                        if (Objects.isNull(id) || StringUtil.isEmpty(name)) {
                            continue;
                        }
                        processFormFilterPojo.setName(name);
                        processFormFilterPojo.setId(id);
                        formFilterPojoList.add(processFormFilterPojo);
                    }
                }
                param.remove("aliasIn");
                param.put("saasMark", SaasMarkEnum.PAAS.getCode());
                List<PaasMenuEntity> menuEntityList = menuModel.list(param);
                menuEntityList.forEach((item) -> {
                    if (isAdmin || menuPermSet.contains(item.getId())) {
                        ProcessFormFilterPojo processFormFilterPojo = new ProcessFormFilterPojo();
                        BeanUtil.copyProperties(item, processFormFilterPojo);
                        formFilterPojoList.add(processFormFilterPojo);
                    }
                });
            } else {
                // 未进行应用筛选
                if (processFormFilterDTO.getAppId() == null) {
                    List<String> saasAlias = new ArrayList<>();
                    Map<String, Long> saasMenuIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (ProcessSaasFormEnum formEnum : ProcessSaasFormEnum.values()) {
                        if (saasPermissions.contains(formEnum.getAlias())) {
                            saasAlias.add(formEnum.getAlias());
                        }
                    }
                    Map<String, Object> param = BeanUtil.convertBean2Map(processFormFilterDTO, true);
                    param.put("saasMark", SaasMarkEnum.SAAS.getCode());
                    param.put("aliasIn", saasAlias);
                    List<PaasMenuEntity> saasMenuList = menuModel.list(param);
                    saasMenuList.forEach((item) -> {
                        saasMenuIdMap.put(item.getAlias() + StringConstant.UNDER_LINE + item.getDistributorMark(), item.getId());
                        saasMenuNameMap.put(item.getAlias() + StringConstant.UNDER_LINE + item.getDistributorMark(), item.getName());

                    });
                    for (ProcessSaasFormEnum formEnum : ProcessSaasFormEnum.values()) {
                        if (saasPermissions.contains(formEnum.getAlias())) {
                            ProcessFormFilterPojo processFormFilterPojo = new ProcessFormFilterPojo();
                            processFormFilterPojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
                            processFormFilterPojo.setBusinessType(XbbRefTypeEnum.transferBusinessType2Index(formEnum.getBusinessType()));
                            String key = ProcessSaasFormEnum.transfer2Saas(formEnum).getAlias() + StringConstant.UNDER_LINE + formEnum.getDistributorMark();
                            String name = saasMenuNameMap.get(key);
                            Long id = saasMenuIdMap.get(key);
                            if (Objects.isNull(id) || StringUtil.isEmpty(name)) {
                                continue;
                            }
                            processFormFilterPojo.setName(name);
                            processFormFilterPojo.setId(id);
                            formFilterPojoList.add(processFormFilterPojo);
                        }
                    }
                }
                Map<String, Object> param = BeanUtil.convertBean2Map(processFormFilterDTO, true);
                param.put("saasMark", SaasMarkEnum.PAAS.getCode());
                List<PaasMenuEntity> menuEntityList = menuModel.list(param);
                if (menuEntityList == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
                }

                menuEntityList.forEach((item) -> {
                    if (isAdmin || menuPermSet.contains(item.getId())) {
                        ProcessFormFilterPojo processFormFilterPojo = new ProcessFormFilterPojo();
                        BeanUtil.copyProperties(item, processFormFilterPojo);
                        formFilterPojoList.add(processFormFilterPojo);
                    }
                });
            }
            processFormFilterVO.setList(formFilterPojoList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasApp数据库查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processFormFilterVO;
    }


    @Override
    public ProcessTypeListVO getProcessTypeList(ProcessTypeListDTO processTypeListDTO) throws XbbException {
        ProcessTypeListVO processTypeListVO = new ProcessTypeListVO();
        List<ProcessTypeClass> processTypeList;
        try {
            String processType = processTypeListDTO.getProcessType();
            if (processType.equals(ProcessTypeEnum.TODO.getValue())) {
                processTypeList = ProcessSearchStatusTodoEnum.getProcessTypeList();
            } else if (processType.equals(ProcessTypeEnum.CREATE.getValue())) {
                processTypeList = ProcessSearchStatusCreateEnum.getProcessTypeList();
            } else if (processType.equals(ProcessTypeEnum.CC.getValue())) {
                processTypeList = ProcessSearchStatusCcEnum.getProcessTypeList();
            } else if (processType.equals(ProcessTypeEnum.ALL.getValue())) {
                processTypeList = ProcessSearchStatusAllEnum.getProcessTypeList();
            } else if (processType.equals(ProcessTypeEnum.HAVE_DONE.getValue())){
                processTypeList = new ArrayList<>();
            } else {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, SystemErrorCodeEnum.API_ERROR_100028.getMsg());
            }
            processTypeListVO.setProcessTypeList(processTypeList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("获取工作流流程状态筛选项出错，platfrom：" + processTypeListDTO.getPlatform(), e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processTypeListVO;
    }
}
